package com.fatgirl.net.socket
{
	import com.fatgirl.net.IMessage;
	import com.fatgirl.net.IProtocol;
	import com.fatgirl.utils.IDCreator;
	
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.Socket;
	import flash.utils.ByteArray;
	import flash.utils.Endian;
	import flash.utils.getQualifiedClassName;
	
	
	/**
	 * socket抽象类  不对外公开
	 * 外部直接调用其派生类 FSocket即可
	 * @author iceman
	 * 
	 */
	internal class AbsSocket implements ISocket
	{	
		private var m_socket:Socket;
		private var m_connSuccFun:Function;
		private var m_closeFun:Function;
		private var m_ioErrorFun:Function;
		private var m_securityErrorFun:Function;
		private var m_connected:Boolean;
		private var m_id:int;
		private var m_IProto:IProtocol;
		private var m_host:String;
		private var m_endian:String = Endian.LITTLE_ENDIAN;
		public function AbsSocket()
		{
			var t_name:String  = getQualifiedClassName(this);
			var t_socket:Socket = new Socket;
			setSocket(t_socket);
			m_id = IDCreator.getAloneID(t_name);//创建一个唯一ID
		}
		/**
		 * 获取 socket 的唯一标识ID 
		 * @return 
		 * 
		 */
		public function get id():int
		{
			return m_id;
		}
		
		/**
		 * 获取协议封装器 
		 * @return 
		 * 
		 */
		public function getProtocol():IProtocol
		{
			return m_IProto;
		}
		/**
		 * 设置协议封装器 
		 * @param _IProto 协议体接口对象
		 * 
		 */
		public function setProtocol(_IProto:IProtocol):void
		{
			m_IProto = _IProto;
		}
		/**
		 * 设置内部socket对象
		 * 主要用在服务器端的socket生成 
		 * @param _socket
		 * 
		 */
		public function setSocket(_socket:Socket):void
		{
			if(m_socket)
			{
				m_socket.removeEventListener(Event.CONNECT,connectHandler);
				m_socket.removeEventListener(Event.CLOSE,closeHandler);
				m_socket.removeEventListener(IOErrorEvent.IO_ERROR,ioErrorHandler);
				m_socket.removeEventListener(ProgressEvent.SOCKET_DATA,readDataHandler);
				m_socket.removeEventListener(SecurityErrorEvent.SECURITY_ERROR,securityErrorHandler);
			}
			m_socket = _socket;
			m_socket.addEventListener(Event.CONNECT,connectHandler);
			m_socket.addEventListener(Event.CLOSE,closeHandler);
			m_socket.addEventListener(IOErrorEvent.IO_ERROR,ioErrorHandler);
			m_socket.addEventListener(ProgressEvent.SOCKET_DATA,readDataHandler);
			m_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR,securityErrorHandler);
		}
		/**
		 * 获取socket实体对象 
		 * @return 
		 * 
		 */
		public function getSocket():Socket
		{
			return m_socket;
		}
		
		/**
		 * 连接 
		 * @param _host
		 * @param _port
		 * 
		 */
		public function connect(_host:String, _port:int):void
		{
			if(!m_socket)
			{
				throw new FatError(FatError.VALUE_IS_NULL);
			}
			m_host = _host;
			m_socket.connect(_host,_port);
			ftrace(this,"开始连接到："+m_host);
		}
		
		/**
		 * 关闭 
		 * 
		 */
		public function close():void
		{
			m_socket.close();
			ftrace(this,m_host+"主动断开socket连接。");
		}
		/**
		 * 虚函数 发送命令 
		 * @param _Icmd
		 * 
		 */
		public function call(_IMessage:IMessage):void
		{
			throw new FatError(FatError.ABSTRACT_FUN);
		}
		public function get connected():Boolean
		{
			return m_connected;
		}
		/**
		 * 字节顺序 
		 * @return 
		 * 
		 */
		public function get endian():String
		{
			return m_endian;
		}
		public function set endian(_vaule:String):void
		{
			m_socket.endian = _vaule;
			m_endian = _vaule;
		}
		protected function send(_byteArr:ByteArray):void
		{
			if(!m_connected)
			{
				ftrace(this,"socket已经被断开无法发送数据........");
				return;
			}
			m_socket.writeBytes(_byteArr,0,_byteArr.length);
			m_socket.flush();
		}
		
		/**
		 * 内部设置缓冲读取数据
		 * @param _byteArr
		 * 
		 */
		protected function read(_byteArr:ByteArray):void
		{
			throw new FatError(FatError.ABSTRACT_FUN);
		}
		private function readDataHandler(e:ProgressEvent):void
		{
			var t_buffer:ByteArray = new ByteArray;
			m_socket.readBytes(t_buffer,0, m_socket.bytesAvailable);
			read(t_buffer);
		}
		private function connectHandler(e:Event):void
		{
			ftrace(this,"socket连接"+m_host+"成功!");
			m_connected = true;
			if(m_connSuccFun!=null)
			{
				m_connSuccFun(this);
			}
		} 
		private function closeHandler(e:Event):void
		{
			ftrace(this,"socket被"+m_host+"断开!");
			m_connected = false;
			if(m_closeFun!=null)
			{
				m_closeFun(this);	
			}
		}
		private function ioErrorHandler(e:IOErrorEvent):void
		{
			ftrace(this,m_host+"socket IO错误!");
			m_connected = false;
			if(m_ioErrorFun!=null)
			{
				m_ioErrorFun(this);
			}
		}
		private function securityErrorHandler(e:SecurityErrorEvent):void
		{
			ftrace(this,m_host+"socket 沙箱错误!");
			m_connected = false;
			if(m_securityErrorFun!=null)
			{
				m_securityErrorFun(this);
			}
		}
		
		
		/**
		 * 设置 沙箱错误回调 
		 * @param value
		 * 
		 */
		public function set securityErrorFun(value:Function):void
		{
			m_securityErrorFun = value;
		}
		
		/**
		 * 设置IO错误回调 
		 * @param value
		 * 
		 */
		public function set ioErrorFun(value:Function):void
		{
			m_ioErrorFun = value;
		}
		
		/**
		 * 设置关闭错误 回调
		 * @param value
		 * 
		 */
		public function set closeFun(value:Function):void
		{
			m_closeFun = value;
		}
		
		/**
		 * 设置连接成功回调 
		 * @param value
		 * 
		 */
		public function set connSuccFun(value:Function):void
		{
			m_connSuccFun = value;
		}
	}
}